<script setup lang="ts">
import type {
  CascaderOption,
  FormInstance,
  FormRules,
} from 'element-plus'
import { useModelLists } from '../../ApplicationModels'
import type { CustomDialogInstance } from '@/types'
import type { ApplicationModel } from '@/types/modules/application-models'

import { saveOrUpdateModelPoint } from '@/api/modules/applicationModel'

defineProps<{
  modalTitle: string
  modelLists: ApplicationModel[]
}>()
const emits = defineEmits<{
  (e: 'save-success'): void
}>()
const dialogRef = ref<CustomDialogInstance>()
const formRef = ref<FormInstance>()

const info = defineModel<
  Omit<ApplicationModel, 'parentId'> & {
    modelId: number
    parentId: number[]
  }
>({ required: true })

const {
  children: nodeLists,
  setChildren,
  getChildrenById,
} = useModelLists()
const computedNodeLists = computed(() => {
  const recursive = (
    array: ApplicationModel[],
  ): CascaderOption[] => {
    return array.map((v) => {
      const children
        = v.children && v.children.length
          ? recursive(v.children)
          : undefined
      return {
        label: v.name,
        value: v.id,
        children,
      }
    })
  }
  return recursive(unref(nodeLists))
})

const rules: FormRules = {
  modelId: [
    {
      required: true,
      message: '请选择应用模型',
      trigger: 'change',
    },
    {
      validator(_rule, value, callback) {
        if (value === 0) {
          callback(new Error('请选择应用模型'))
        }
        else {
          callback()
        }
      },
    },
  ],
  name: [
    {
      required: true,
      message: '请输入节点名称',
    },
    {
      min: 2,
      max: 10,
      message: '长度在 2 到 10 个字符',
    },
  ],
}

function updateChildren(modelId: number) {
  if (modelId) {
    getChildrenById(modelId)
  }
  else {
    setChildren([])
  }
}

async function clickSave(done: () => void) {
  const isValid = await formRef.value
    ?.validate()
    .catch(() => {
      done()
    })
  if (isValid) {
    try {
      const { name, id, modelId, parentId } = unref(info)
      await saveOrUpdateModelPoint({
        id: id === 0 ? undefined : id,
        parentId: (Array.isArray(parentId) && parentId.length > 0) ? parentId[parentId.length - 1] : modelId, // 如果父模型节点没选则保存在模型下
        name,
      })
      done()
      close()
      ElMessage.success('保存成功')
      emits('save-success')
    }
    catch (e) {
      console.log(e)
      done()
    }
  }
}

function open() {
  updateChildren(unref(info).modelId)
  dialogRef.value?.open()
}
function close() {
  dialogRef.value?.close()
}

defineExpose({ open, close })
</script>

<template>
  <CustomDialog
    ref="dialogRef"
    :title="modalTitle"
    width="600px"
    need-saving
    @confirm="clickSave"
  >
    <ElForm
      ref="formRef"
      :model="info"
      :rules="rules"
      label-position="top"
    >
      <ElFormItem label="应用模型" prop="modelId" for="model_id">
        <ElSelect
          v-model="info.modelId"
          class="width-100"
          placeholder="请选择应用模型"
          @change="updateChildren"
        >
          <ElOption
            label="请选择"
            :value="0"
            disabled
          />
          <ElOption
            v-for="item in modelLists"
            :key="item.id"
            :label="item.name"
            :value="item.id"
          />
        </ElSelect>
      </ElFormItem>
      <ElFormItem label="父节点" prop="parentId" for="parent_id">
        <ElCascader
          v-model="info.parentId"
          class="width-100"
          :props="{
            checkStrictly: true,
            expandTrigger: 'hover',
          }"
          clearable
          :options="computedNodeLists"
          placeholder="请选择父节点（可选）"
        />
      </ElFormItem>
      <ElFormItem label="节点名称" prop="name" for="name">
        <ElInput
          v-model.trim="info.name"
          :maxlength="10"
          :minlength="2"
          placeholder="请输入节点名称，字数不超过10个"
        />
      </ElFormItem>
    </ElForm>
  </CustomDialog>
</template>
